package cn.nexd.app.indoor.presenter;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import cn.nexd.app.indoor.Config;
import cn.nexd.app.indoor.R;
import cn.nexd.app.indoor.application.MyApplication;
import cn.nexd.app.indoor.model.FloorModel;
import cn.nexd.app.indoor.model.MallModel;
import cn.nexd.app.indoor.overyly.MarkerOverlay;
import cn.nexd.app.indoor.perimission.CheckPermission;
import cn.nexd.app.indoor.routeplan.Dijkstra;
import cn.nexd.app.indoor.routeplan.Vertex;
import cn.nexd.app.indoor.ui.activity.NexdMapActivity;
import cn.nexd.app.indoor.ui.iView.INexdMapActivityView;
import cn.nexd.app.indoor.util.DateUtil;
import cn.nexd.app.indoor.util.FileUtil;
import cn.nexd.app.indoor.util.SplineUtil;
import cn.nexd.location.indoor.NexdIndoorLocation;
import cn.nexd.location.indoor.NexdIndoorLocationAgent;
import cn.nexd.location.indoor.NexdIndoorLocationConfiguration;
import cn.nexd.location.indoor.NexdIndoorLocationResult;
import cn.nexd.location.indoor.listener.NexdIndoorLocationListener;
import cn.nexd.map.rendering.POIData;
import cn.nexd.map.rendering.core.componet.SVGMapView;
import cn.nexd.map.rendering.overlay.SVGMapLinesOverlay;
import cn.nexd.map.rendering.overlay.SVGMapLocationOverlay;

/**
 * Created by wangxu on 16/7/20.
 */
public class NexdMapPresenter extends BasePresenter<INexdMapActivityView> {

    private final String TAG = getClass().getSimpleName();
    private FloorModel floorModel;
    private NexdIndoorLocationAgent nexdIndoorLocationAgent;
    private SVGMapView nexdMap;
    private MallModel mallModel;
    private String mallPath = ""; // 加载路径
    private SVGMapLocationOverlay svgMapLocationOverlay; // 定位图层
    private PointF locationPointF; // 路径规划起点
    private Dijkstra dijkstra;
    private SVGMapLinesOverlay linesOverlay;
    private MarkerOverlay startMarkOverlay;
    private MarkerOverlay endMarkOverlay;
    private long lastFloorId = 0;
    private List<PointF> routePlanPointFs;

    private PointF lastLocationPointF;

    private PointF locationPointf;


    private int index = 1; // 用来计数没用点的个数,成功后会重置

    private PointF lastPointf; // 上一次定位点

    private int Defaule_Distacne = 2;// 默认人行走的距离为2m
    private List<PointF> list;

    public NexdMapPresenter(Context context, INexdMapActivityView iView) {
        super(context, iView);
        this.dijkstra = new Dijkstra();
    }

    public void setNexdMap(SVGMapView nexdMap) {
        this.nexdMap = nexdMap;
    }

    public void setMallModel(MallModel mallModel) {
        this.mallModel = mallModel;
        this.mallPath = Config.BASE_FILE_PATH + mallModel.getMallId() + File.separator;
    }


    public List<String> initARItem(List<FloorModel> floorModels) {

        List<String> itemNames = new ArrayList<>();
        for (FloorModel model : floorModels) {
            itemNames.add(model.getFloorName());
        }
        return itemNames;
    }

    public void initLocation() {
        nexdIndoorLocationAgent = NexdIndoorLocationAgent.getIndoorLocationAgent(context);
        NexdIndoorLocationConfiguration.Buidler config = new NexdIndoorLocationConfiguration.Buidler();
        config.setAppkey("");
        config.setLocationRate(MyApplication.LOCATION_TIME * 1000); // 定位时间间隔
        if (MyApplication.IS_BEACON && MyApplication.IS_WIFI) {
            config.setLocationMode(NexdIndoorLocationConfiguration.LocationMode.LOCATION_MODE_MIX);
            Log.d(TAG, "initMap: Mix Mode");
        } else if (MyApplication.IS_WIFI) {
            config.setLocationMode(NexdIndoorLocationConfiguration.LocationMode.LOCATION_MODE_WIFI_ONLY);
            Log.d(TAG, "initMap: Wifi Mode");
        } else if (MyApplication.IS_BEACON) {
            config.setLocationMode(NexdIndoorLocationConfiguration.LocationMode.LOCATION_MODE_BEACON_ONLY);
            Log.d(TAG, "initMap: Beacon Mode");
        }
//        config.setLocationConfigPath("/sdcard/nexd/map/");
        nexdIndoorLocationAgent.setIndoorLocationConfiguration(config.build());


        nexdIndoorLocationAgent.setIndoorLocationListener(new NexdIndoorLocationListener() {
            @Override
            public void onLocationStart(long l, long l1, NexdIndoorLocationConfiguration.LocationMode locationMode) {

            }

            @Override
            public void onLocationSuccess(NexdIndoorLocationResult nexdIndoorLocationResult) {

                // TODO: 16/6/29  滑动显示坐标,以及防止坐标大跳的算法逻辑
                // 滑动算法
//                List<PointF> pointFs = recalas(new PointF(nexdIndoorLocationResult.getLocationResultX(), nexdIndoorLocationResult.getLocationResultY()));
//                PointF current = recalas(new PointF(nexdIndoorLocationResult.getLocationResultX(), nexdIndoorLocationResult.getLocationResultY()));
//                try {
////                    for (PointF current : pointFs) {
//                    if (MyApplication.IS_SMOOTH_OUTPUT) {
//                        Log.d("LocationListener", "进入平滑输出");
////                             平滑输出
//                        if (svgMapLocationOverlay == null) {
//                            Log.d("svgMapLocationOverlay", "我不是空!");
//                            svgMapLocationOverlay = new SVGMapLocationOverlay(nexdMap);
//                        }
//                        if (nexdMap.isMapLoadFinsh()) {
//                            Log.i("LocationOverlay", "add overlay");
//                            Log.d("locationPoints", current.x + ",,,," + current.y);
//                            PointF currentLocationPointF;
//                            if (lastLocationPointF != null) {
//                                currentLocationPointF = SplineUtil.getPoint(lastLocationPointF, current);
//                            } else {
//                                currentLocationPointF = current;
//                            }
//                            if (locationPointF == null) {
//                                locationPointF = new PointF(currentLocationPointF.x - nexdMap.getFloorFeature().getOffset_x(), currentLocationPointF.y - nexdMap.getFloorFeature().getOffset_y());
//                            } else {
//                                locationPointF = new PointF(currentLocationPointF.x - nexdMap.getFloorFeature().getOffset_x(), currentLocationPointF.y - nexdMap.getFloorFeature().getOffset_y());
//                            }
//                            lastLocationPointF = currentLocationPointF;
////                                当前定位点
//                            svgMapLocationOverlay.setPosition(currentLocationPointF);
//                            iView.addOverlay(svgMapLocationOverlay, NexdMapActivity.MARK_TYPE_LOCATION);
//                            NexdMapActivity.IS_LOCATIONING = true;
//                        }
//                    } else {
////                             正常定位
//                        Log.d("LocationListener", "进入非平滑输出");
//                        if (svgMapLocationOverlay == null) {
//                            Log.d("svgMapLocationOverlay", "我不是空!");
//                            svgMapLocationOverlay = new SVGMapLocationOverlay(nexdMap);
//                        }
//                        if (nexdMap.isMapLoadFinsh()) {
//                            Log.i("LocationOverlay", "add overlay");
//                            Log.d("locationPoints", current.x + ",,,," + current.y);
//                            if (locationPointF == null) {
//                                locationPointF = new PointF(current.x - nexdMap.getFloorFeature().getOffset_x(), current.y - nexdMap.getFloorFeature().getOffset_y());
//                            } else {
//                                locationPointF.set(current.x - nexdMap.getFloorFeature().getOffset_x(), current.y - nexdMap.getFloorFeature().getOffset_y());
//                            }
////                                当前定位点
//                            svgMapLocationOverlay.setPosition(current);
//                            iView.addOverlay(svgMapLocationOverlay, NexdMapActivity.MARK_TYPE_LOCATION);
//                            NexdMapActivity.IS_LOCATIONING = true;
//                        }
////                    }
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }


                // // TODO: 16/6/28  edit by tony   原始定位显示逻辑
                if (MyApplication.IS_SMOOTH_OUTPUT) {
                    Log.d("LocationListener", "进入平滑输出");
                    // 平滑输出
                    if (svgMapLocationOverlay == null) {
                        Log.d("svgMapLocationOverlay", "我不是空!");
                        svgMapLocationOverlay = new SVGMapLocationOverlay(nexdMap);
                        iView.addOverlay(svgMapLocationOverlay, NexdMapActivity.MARK_TYPE_LOCATION);
                    }
                    if (nexdMap.isMapLoadFinsh()) {
                        Log.i("LocationOverlay", "add overlay");
                        Log.d("locationPoints", nexdIndoorLocationResult.getLocationResultX() + ",,,," + nexdIndoorLocationResult.getLocationResultY());
                        PointF currentLocationPointF;
                        if (lastLocationPointF != null) {
                            currentLocationPointF = SplineUtil.getPoint(lastLocationPointF, new PointF(nexdIndoorLocationResult.getLocationResultX(), nexdIndoorLocationResult.getLocationResultY()));
                        } else {
                            currentLocationPointF = new PointF(nexdIndoorLocationResult.getLocationResultX(), nexdIndoorLocationResult.getLocationResultY());
                        }
                        if (locationPointF == null) {
                            locationPointF = new PointF(currentLocationPointF.x - nexdMap.getFloorFeature().getOffset_x(), currentLocationPointF.y - nexdMap.getFloorFeature().getOffset_y());
                        } else {
                            locationPointF = new PointF(currentLocationPointF.x - nexdMap.getFloorFeature().getOffset_x(), currentLocationPointF.y - nexdMap.getFloorFeature().getOffset_y());
                        }
                        lastLocationPointF = currentLocationPointF;
                        //当前定位点
                        svgMapLocationOverlay.setPosition(currentLocationPointF);
                        NexdMapActivity.IS_LOCATIONING = true;
                    }
                } else {
                    // 正常定位
                    Log.d("LocationListener", "进入非平滑输出");
                    if (svgMapLocationOverlay == null) {
                        Log.d("svgMapLocationOverlay", "我不是空!");
                        svgMapLocationOverlay = new SVGMapLocationOverlay(nexdMap);
                    }
                    if (nexdMap.isMapLoadFinsh()) {
                        Log.i("LocationOverlay", "add overlay");
                        Log.d("locationPoints", nexdIndoorLocationResult.getLocationResultX() + ",,,," + nexdIndoorLocationResult.getLocationResultY());
                        if (locationPointF == null) {
                            locationPointF = new PointF(nexdIndoorLocationResult.getLocationResultX() - nexdMap.getFloorFeature().getOffset_x(), nexdIndoorLocationResult.getLocationResultY() - nexdMap.getFloorFeature().getOffset_y());
                        } else {
                            locationPointF.set(nexdIndoorLocationResult.getLocationResultX() - nexdMap.getFloorFeature().getOffset_x(), nexdIndoorLocationResult.getLocationResultY() - nexdMap.getFloorFeature().getOffset_y());
                        }
                        //当前定位点
                        svgMapLocationOverlay.setPosition(new PointF(nexdIndoorLocationResult.getLocationResultX(), nexdIndoorLocationResult.getLocationResultY()));
                        NexdMapActivity.IS_LOCATIONING = true;
                    }
                }
                nexdMap.refresh();
            }

            @Override
            public void onLocationFailed(NexdIndoorLocation.LocationState locationState) {
                Log.e(TAG, "onLocationFailed: " + locationState.toString());
            }

            @Override
            public void onLocationInterrupt(NexdIndoorLocation.LocationState locationState) {
                Log.e(TAG, "onLocationInterrupt: " + locationState.toString());

            }
        });
    }

    public void loadMap(FloorModel floorModel) {
        this.floorModel = floorModel;
        // 加载当前楼层的路网数据
        if (MyApplication.IS_ROUTE_PLAN) {
            try {
                dijkstra.load_config(Config.BASE_FILE_PATH + mallModel.getMallId() + "/" + floorModel.getFloorId() + ".road");
            } catch (Exception e) {
                MyApplication.getInstance().reportException(e);
            }
        }
        Log.d("svgPath", getSvgPath(floorModel.getFloorSvg()));
        if (!CheckPermission.checkPermission((Activity) context, "android.permission.WRITE_EXTERNAL_STORAGE")
                || !CheckPermission.checkPermission((Activity) context, "android.permission.READ_EXTERNAL_STORAGE")) {
            iView.showToast("存储权限被拒绝,请在设置中允许");
            return;
        }
        if (checkFileExist(getSvgPath(floorModel.getFloorSvg()))) {
            iView.loadMap(getSvgPath(floorModel.getFloorSvg()));
        } else {
            iView.showToast("未找到当前楼层信息");
        }
    }

    private boolean checkFileExist(String svgPath) {
        return FileUtil.checkExist(svgPath);
    }

    private String getSvgPath(String floorSvg) {
        return mallPath + floorSvg;
    }

    public void setCurrentFloor(FloorModel floorModel) {
        this.floorModel = floorModel;
        lastLocationPointF = null;
        nexdMap.removeOverlay(NexdMapActivity.MARK_TYPE_LOCATION);
        String svgPath = getSvgPath(floorModel.getFloorSvg());
        Log.d("切换楼层", svgPath);
        try {
            dijkstra.load_config(Config.BASE_FILE_PATH + mallModel.getMallId() + "/" + floorModel.getFloorId() + ".road");
        } catch (IOException e) {
            MyApplication.getInstance().reportException(e);
        }
        if (checkFileExist(svgPath)) {
            iView.setCurrentFloor(svgPath);
        } else {
            iView.showToast("未找到当前楼层信息");
        }
    }

    public boolean routePlanPOI2POI(POIData startPoiData, POIData endPoiData) {

        if (dijkstra == null) {
            iView.showToast(context.getString(R.string.dijkstra_data_null));
            return false;
        }
        List<Vertex> points;
        points = dijkstra.get_path_poi_poi(startPoiData.getPoi_id(), endPoiData.getPoi_id());

        if (points == null || points.size() == 0) {
            iView.showToast("无法规划路线到目的地");
            return false;
        }
        if (startMarkOverlay == null) {
            startMarkOverlay = new MarkerOverlay(context);
        }

        PointF currentPointF = new PointF(startPoiData.getCenter_x(), startPoiData.getCenter_y());
        startMarkOverlay.setPosition(currentPointF);
        startMarkOverlay.setRes(R.drawable.icon_st);
        iView.addOverlay(startMarkOverlay, NexdMapActivity.MARK_TYPE_MARKER);

        if (endMarkOverlay == null) {
            endMarkOverlay = new MarkerOverlay(context);
        }
        endMarkOverlay.setPosition(new PointF(endPoiData.getCenter_x(), endPoiData.getCenter_y()));
        endMarkOverlay.setRes(R.drawable.icon_en);
        iView.addOverlay(endMarkOverlay, NexdMapActivity.MARK_TYPE_MARKER);

        if (linesOverlay == null) {
            linesOverlay = new SVGMapLinesOverlay(nexdMap);
        }
        // 开始规划路线
        if (routePlanPointFs == null) {
            routePlanPointFs = new ArrayList<>();
        } else {
            routePlanPointFs.clear();
        }
        routePlanPointFs.add(currentPointF);

        for (Vertex vertex : points) {
            routePlanPointFs.add(new PointF((float) vertex.location[0], (float) vertex.location[1]));

        }
        linesOverlay.setPositions(routePlanPointFs);
        iView.addOverlay(linesOverlay, NexdMapActivity.MARK_TYPE_ROUTE_PLAN);

        iView.resetRoutePlan();
        return true;
    }

    public boolean routePlanXY2POI(POIData endPoiData) {
        if (locationPointF == null) {
            iView.showToast("定位中...");
            return false;
        }

        if (dijkstra == null) {
            iView.showToast(context.getString(R.string.dijkstra_data_null));
            return false;
        }
        // 路径规划计算
        PointF currentLocation = getCurrentLocationPointF();
        List<Vertex> points;
        try {
            points = dijkstra.get_path_poi(
                    new double[]{currentLocation.x, currentLocation.y},
                    endPoiData.getPoi_id(),
                    endPoiData.getFloor_id());

        } catch (ArrayIndexOutOfBoundsException e) {
            iView.showToast("无法规划路线到目的地");
            MyApplication.getInstance().reportException(e);
            e.printStackTrace();
            return false;
        }

        // 判断是否可以到达指定地点
        if (points == null || points.size() == 0) {
            iView.showToast("无法规划路线到目的地");
            return false;
        }

        if (startMarkOverlay == null) {
            startMarkOverlay = new MarkerOverlay(context);
        }

        startMarkOverlay.setPosition(currentLocation);
        startMarkOverlay.setRes(R.drawable.icon_st);
        iView.addOverlay(startMarkOverlay, NexdMapActivity.MARK_TYPE_MARKER);

        if (endMarkOverlay == null) {
            endMarkOverlay = new MarkerOverlay(context);
        }
        endMarkOverlay.setPosition(new PointF(endPoiData.getCenter_x(), endPoiData.getCenter_y()));
        endMarkOverlay.setRes(R.drawable.icon_en);
        iView.addOverlay(endMarkOverlay, NexdMapActivity.MARK_TYPE_MARKER);

        if (linesOverlay == null) {
            linesOverlay = new SVGMapLinesOverlay(nexdMap);
        }
        // 开始规划路线
        if (routePlanPointFs == null) {
            routePlanPointFs = new ArrayList<>();
        } else {
            routePlanPointFs.clear();
        }
        routePlanPointFs.add(currentLocation);

        for (Vertex vertex : points) {
            routePlanPointFs.add(new PointF((float) vertex.location[0], (float) vertex.location[1]));
        }
        linesOverlay.setPositions(routePlanPointFs);
        iView.addOverlay(linesOverlay, NexdMapActivity.MARK_TYPE_ROUTE_PLAN);
        iView.resetRoutePlan();
        return true;
    }

    private PointF getCurrentLocationPointF() {

        return new PointF(locationPointF.x, locationPointF.y);
    }

    public void saveNexdMap(Bitmap bitmap) {
        if (!CheckPermission.checkPermission((Activity) context, "android.permission.WRITE_EXTERNAL_STORAGE")
                || !CheckPermission.checkPermission((Activity) context, "android.permission.READ_EXTERNAL_STORAGE")) {
            iView.showToast("存储权限被拒绝,请在设置中允许");
            return;
        }
        // 当前地图截图
        String fileName = Config.BASE_FILE_PATH + File.separator + "img" + File.separator + DateUtil.getCurrentByType("yyyyMMDDHHmmss") + ".png";
        File file = FileUtil.buildFile(fileName, false);
        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
        } catch (IOException e) {
            MyApplication.getInstance().reportException(e);
        }
    }

    public void startLocation() {
        if (MyApplication.AUTO_CHANGE_FLOOR) {
            nexdIndoorLocationAgent.startLocation(Long.parseLong(mallModel.getMallId()));
            Log.d(TAG, "startLocation: Auto_Change_Floor");
        } else {
            nexdIndoorLocationAgent.startLocation(Long.parseLong(mallModel.getMallId()), Long.parseLong(floorModel.getFloorId()));
            Log.d(TAG, "startLocation: Not Auto_Change_Floor");
        }
    }

    public void stopLocation() {
        nexdIndoorLocationAgent.stopLocation();
        Log.d(TAG, "stopLocation: 定位停止");
    }

    public void destory() {
        nexdIndoorLocationAgent.destroyLocation();
    }
}
